using System;
using System.Collections.Generic;
using System.Text;

namespace OracleInternal.I18N
{
	[Serializable]
	internal class TLBConv1Byte : TLBConv
	{
		private const int ORACHARMASK = 255;

		private const int UCSCHARWIDTH = 16;

		public int m_ucsReplacement;

		public int[] m_ucsChar;

		public char[] m_oraCharLevel1;

		public char[] m_oraCharSurrogateLevel;

		public char[] m_oraCharLevel2;

		public byte m_oraCharReplacement;

		internal bool noSurrogate = true;

		internal bool strictASCII = true;

		internal int m_oraCharLevel2Size;

		public override int MinBytesPerChar => 1;

		public override int MaxBytesPerChar => 1;

		public TLBConv1Byte()
		{
			m_groupId = 0;
		}

		private int ByteToChar(byte srcChar, bool useReplacement)
		{
			int num = m_ucsChar[srcChar & 0xFF];
			if (num == 65535)
			{
				if (!useReplacement)
				{
					throw new DecoderFallbackException(I18nStringResourceManager.GetErrorMesg("FAIL_CONV_TO_UNICODE"));
				}
				return m_oraCharReplacement;
			}
			return num;
		}

		private byte CharToByte(char srcChar, char lowSurrogate, bool useReplacement)
		{
			int num = ((int)srcChar >> 8) & 0xFF;
			int num2 = srcChar & 0xFF;
			int num3 = ((int)lowSurrogate >> 8) & 0xFF;
			int num4 = lowSurrogate & 0xFF;
			if (m_oraCharLevel1[num] != (ushort)m_oraCharLevel2Size && m_oraCharSurrogateLevel[m_oraCharLevel1[num] + num2] != '\uffff' && m_oraCharSurrogateLevel[m_oraCharSurrogateLevel[m_oraCharLevel1[num] + num2] + num3] != '\uffff' && m_oraCharLevel2[m_oraCharSurrogateLevel[m_oraCharSurrogateLevel[m_oraCharLevel1[num] + num2] + num3] + num4] != '\uffff')
			{
				return (byte)m_oraCharLevel2[m_oraCharSurrogateLevel[m_oraCharSurrogateLevel[m_oraCharLevel1[num] + num2] + num3] + num4];
			}
			if (useReplacement)
			{
				return m_oraCharReplacement;
			}
			throw new DecoderFallbackException(I18nStringResourceManager.GetErrorMesg("FAIL_CONV_TO_BYTES"));
		}

		private byte CharToByte(char srcChar, bool useReplacement)
		{
			int num = (int)srcChar >> 8;
			int num2 = srcChar & 0xFF;
			char c;
			if ((c = m_oraCharLevel2[m_oraCharLevel1[num] + num2]) != '\uffff')
			{
				return (byte)c;
			}
			if (useReplacement)
			{
				return m_oraCharReplacement;
			}
			throw new DecoderFallbackException(I18nStringResourceManager.GetErrorMesg("FAIL_CONV_TO_BYTES"));
		}

		public override int ConvertBytesToChars(byte[] bytes, int offset, int count, char[] chars, int charOffset, ref int charCount, bool ccb)
		{
			int num = offset;
			if (num < 0)
			{
				num = 0;
			}
			int num2 = num + count;
			if (num2 > bytes.Length)
			{
				num2 = bytes.Length;
			}
			int num3 = charOffset;
			if (num3 < 0)
			{
				num3 = 0;
			}
			int num4 = num3 + charCount;
			if (num4 > chars.Length)
			{
				num4 = chars.Length;
			}
			while (num < num2 && num3 < num4)
			{
				int num5 = m_ucsChar[bytes[num++] & 0xFF];
				if (num5 == 65535)
				{
					if (!ccb)
					{
						throw new DecoderFallbackException(I18nStringResourceManager.GetErrorMesg("FAIL_CONV_TO_UNICODE"));
					}
					chars[num3++] = (char)m_ucsReplacement;
				}
				else
				{
					chars[num3++] = (char)num5;
				}
			}
			charCount = num3 - charOffset;
			return num - offset;
		}

		public override int ConvertBytesToUTF16(byte[] bytes, int offset, int count, byte[] utfbytes, int utfOffset, ref int utfCount, bool ccb)
		{
			int num = offset;
			if (num < 0)
			{
				num = 0;
			}
			int num2 = num + count;
			if (num2 > bytes.Length)
			{
				num2 = bytes.Length;
			}
			int num3 = utfOffset;
			if (num3 < 0)
			{
				num3 = 0;
			}
			int num4 = num3 + utfCount;
			if (num4 > utfbytes.Length)
			{
				num4 = utfbytes.Length;
			}
			while (num < num2 && num3 + 1 < num4)
			{
				int num5 = m_ucsChar[bytes[num++] & 0xFF];
				if (num5 == 65535)
				{
					if (!ccb)
					{
						throw new DecoderFallbackException(I18nStringResourceManager.GetErrorMesg("FAIL_CONV_TO_UNICODE"));
					}
					utfbytes[num3++] = (byte)((ushort)m_ucsReplacement & 0xFFu);
					utfbytes[num3++] = (byte)((ushort)m_ucsReplacement >> 8);
				}
				else
				{
					utfbytes[num3++] = (byte)((ushort)num5 & 0xFFu);
					utfbytes[num3++] = (byte)((ushort)num5 >> 8);
				}
			}
			utfCount = num3 - utfOffset;
			return num - offset;
		}

		public override int ConvertCharsToBytes(char[] chars, int chars_offset, int chars_count, byte[] bytes, int bytes_begin, ref int bytes_count, bool ccb)
		{
			int num = chars_offset;
			int num2 = chars_offset + chars_count;
			if (num < 0)
			{
				num = 0;
			}
			if (num2 > chars.Length)
			{
				num2 = chars.Length;
			}
			if (bytes_begin < 0)
			{
				bytes_begin = 0;
			}
			int num3 = bytes_begin + bytes_count;
			if (num3 > bytes.Length)
			{
				num3 = bytes.Length;
			}
			int num4 = bytes_begin;
			int i;
			for (i = num; i < num2; i++)
			{
				if (num4 >= num3)
				{
					break;
				}
				if (chars[i] >= '\ud800' && chars[i] < '\udc00')
				{
					if (i + 1 < num2 && chars[i + 1] >= '\udc00' && chars[i + 1] <= '\udfff')
					{
						if (noSurrogate)
						{
							if (!ccb)
							{
								throw new DecoderFallbackException(I18nStringResourceManager.GetErrorMesg("FAIL_CONV_TO_BYTES"));
							}
							bytes[num4++] = m_oraCharReplacement;
						}
						else
						{
							bytes[num4++] = CharToByte(chars[i], chars[i + 1], ccb);
						}
						i++;
					}
					else
					{
						if (!ccb)
						{
							throw new DecoderFallbackException(I18nStringResourceManager.GetErrorMesg("FAIL_CONV_TO_BYTES"));
						}
						bytes[num4++] = m_oraCharReplacement;
					}
					continue;
				}
				if (chars[i] < '\u0080' && strictASCII)
				{
					bytes[num4++] = (byte)chars[i];
					continue;
				}
				int num5 = (int)chars[i] >> 8;
				int num6 = chars[i] & 0xFF;
				char c;
				if ((c = m_oraCharLevel2[m_oraCharLevel1[num5] + num6]) != '\uffff')
				{
					bytes[num4++] = (byte)c;
					continue;
				}
				if (ccb)
				{
					bytes[num4++] = m_oraCharReplacement;
					continue;
				}
				throw new DecoderFallbackException(I18nStringResourceManager.GetErrorMesg("FAIL_CONV_TO_BYTES"));
			}
			bytes_count = num4 - bytes_begin;
			return i - num;
		}

		public override int ConvertStringToBytes(string chars, int chars_offset, int chars_count, byte[] bytes, int bytes_begin, ref int bytes_count, bool ccb)
		{
			int num = chars_offset;
			int num2 = chars_offset + chars_count;
			if (num < 0)
			{
				num = 0;
			}
			if (num2 > chars.Length)
			{
				num2 = chars.Length;
			}
			if (bytes_begin < 0)
			{
				bytes_begin = 0;
			}
			int num3 = bytes_begin + bytes_count;
			if (num3 > bytes.Length)
			{
				num3 = bytes.Length;
			}
			int num4 = bytes_begin;
			int i;
			for (i = num; i < num2; i++)
			{
				if (num4 >= num3)
				{
					break;
				}
				if (chars[i] >= '\ud800' && chars[i] < '\udc00')
				{
					if (i + 1 < num2 && chars[i + 1] >= '\udc00' && chars[i + 1] <= '\udfff')
					{
						if (noSurrogate)
						{
							if (!ccb)
							{
								throw new DecoderFallbackException(I18nStringResourceManager.GetErrorMesg("FAIL_CONV_TO_BYTES"));
							}
							bytes[num4++] = m_oraCharReplacement;
						}
						else
						{
							bytes[num4++] = CharToByte(chars[i], chars[i + 1], ccb);
						}
						i++;
					}
					else
					{
						if (!ccb)
						{
							throw new DecoderFallbackException(I18nStringResourceManager.GetErrorMesg("FAIL_CONV_TO_BYTES"));
						}
						bytes[num4++] = m_oraCharReplacement;
					}
					continue;
				}
				if (chars[i] < '\u0080' && strictASCII)
				{
					bytes[num4++] = (byte)chars[i];
					continue;
				}
				int num5 = (int)chars[i] >> 8;
				int num6 = chars[i] & 0xFF;
				char c;
				if ((c = m_oraCharLevel2[m_oraCharLevel1[num5] + num6]) != '\uffff')
				{
					bytes[num4++] = (byte)c;
					continue;
				}
				if (ccb)
				{
					bytes[num4++] = m_oraCharReplacement;
					continue;
				}
				throw new DecoderFallbackException(I18nStringResourceManager.GetErrorMesg("FAIL_CONV_TO_BYTES"));
			}
			bytes_count = num4 - bytes_begin;
			return i - num;
		}

		public override int ConvertUTF16ToBytes(byte[] utf16Bytes, int utf16BytesOffset, int utf16BytesCount, byte[] bytes, int byteOffset, ref int byteCount, bool ccb)
		{
			int num = utf16BytesOffset;
			int num2 = num + utf16BytesCount;
			if (num < 0)
			{
				num = 0;
			}
			if (num2 > utf16Bytes.Length)
			{
				num2 = utf16Bytes.Length;
			}
			if (byteOffset < 0)
			{
				byteOffset = 0;
			}
			int num3 = byteOffset + byteCount;
			if (num3 > bytes.Length)
			{
				num3 = bytes.Length;
			}
			int num4 = byteOffset;
			int i;
			for (i = num; i < num2 - 1; i += 2)
			{
				if (num4 >= num3)
				{
					break;
				}
				char c = (char)((utf16Bytes[i + 1] << 8) | utf16Bytes[i]);
				if (c >= '\ud800' && c < '\udc00')
				{
					if (i + 3 >= num2)
					{
						continue;
					}
					char c2 = (char)((utf16Bytes[i + 3] << 8) | utf16Bytes[i + 2]);
					if (c2 >= '\udc00' && c2 <= '\udfff')
					{
						if (noSurrogate)
						{
							if (!ccb)
							{
								throw new DecoderFallbackException(I18nStringResourceManager.GetErrorMesg("FAIL_CONV_TO_BYTES"));
							}
							bytes[num4++] = m_oraCharReplacement;
						}
						else
						{
							bytes[num4++] = CharToByte(c, c2, ccb);
						}
						i += 2;
					}
					else
					{
						if (!ccb)
						{
							throw new DecoderFallbackException(I18nStringResourceManager.GetErrorMesg("FAIL_CONV_TO_BYTES"));
						}
						bytes[num4++] = m_oraCharReplacement;
					}
					continue;
				}
				if (c < '\u0080' && strictASCII)
				{
					bytes[num4++] = (byte)c;
					continue;
				}
				int num5 = (int)c >> 8;
				int num6 = c & 0xFF;
				char c3;
				if ((c3 = m_oraCharLevel2[m_oraCharLevel1[num5] + num6]) != '\uffff')
				{
					bytes[num4++] = (byte)c3;
					continue;
				}
				if (ccb)
				{
					bytes[num4++] = m_oraCharReplacement;
					continue;
				}
				throw new DecoderFallbackException(I18nStringResourceManager.GetErrorMesg("FAIL_CONV_TO_BYTES"));
			}
			byteCount = num4 - byteOffset;
			return i - num;
		}

		public override bool IsOraCharacterReplacement(char ch, char lowsur)
		{
			if (lowsur != 0)
			{
				return CharToByte(ch, lowsur, useReplacement: true) == m_oraCharReplacement;
			}
			return CharToByte(ch, useReplacement: true) == m_oraCharReplacement;
		}

		public override void BuildUnicodeToOracleMapping()
		{
			m_oraCharLevel1 = new char[256];
			m_oraCharSurrogateLevel = null;
			m_oraCharLevel2 = null;
			IList<int[]> list = new List<int[]>(45055);
			Dictionary<int, char[]> dictionary = new Dictionary<int, char[]>();
			Dictionary<int, char[]> dictionary2 = new Dictionary<int, char[]>();
			int num = m_ucsChar.Length;
			char c = '\0';
			char c2 = '\0';
			for (int i = 0; i < 256; i++)
			{
				m_oraCharLevel1[i] = '\uffff';
			}
			for (int i = 0; i < num; i++)
			{
				int num2 = m_ucsChar[i];
				if (num2 != 65535 && num2 != m_ucsReplacement)
				{
					list.Add(new int[2]
					{
						num2,
						i
					});
					StoreMappingRange(num2, dictionary, dictionary2);
				}
			}
			if (extraUnicodeToOracleMapping != null)
			{
				num = extraUnicodeToOracleMapping.Length;
				for (int i = 0; i < num; i++)
				{
					int num2 = extraUnicodeToOracleMapping[i][0];
					if (num2 != m_ucsReplacement)
					{
						StoreMappingRange(num2, dictionary, dictionary2);
					}
				}
			}
			int num3 = 0;
			int num4 = 0;
			foreach (KeyValuePair<int, char[]> item in dictionary)
			{
				if (item.Value != null)
				{
					num3 += 256;
				}
			}
			foreach (KeyValuePair<int, char[]> item2 in dictionary2)
			{
				if (item2.Value != null)
				{
					num4 += 256;
				}
			}
			if (num3 != 0)
			{
				m_oraCharSurrogateLevel = new char[num3];
			}
			if (num4 != 0)
			{
				m_oraCharLevel2 = new char[num4 + 256];
			}
			for (int i = 0; i < num3; i++)
			{
				m_oraCharSurrogateLevel[i] = '\uffff';
			}
			for (int i = 0; i < num4 + 256; i++)
			{
				m_oraCharLevel2[i] = '\uffff';
			}
			for (int i = 0; i < list.Count; i++)
			{
				int[] array = list[i];
				if (array[0] == m_ucsReplacement)
				{
					continue;
				}
				int num5 = (array[0] >> 24) & 0xFF;
				int num6 = (array[0] >> 16) & 0xFF;
				int num7 = (array[0] >> 8) & 0xFF;
				int num8 = array[0] & 0xFF;
				if (num5 >= 216 && num5 < 220)
				{
					if (m_oraCharLevel1[num5] == '\uffff')
					{
						m_oraCharLevel1[num5] = c2;
						c2 = (char)(c2 + 256);
					}
					if (m_oraCharSurrogateLevel[m_oraCharLevel1[num5] + num6] == '\uffff')
					{
						m_oraCharSurrogateLevel[m_oraCharLevel1[num5] + num6] = c2;
						c2 = (char)(c2 + 256);
					}
					if (m_oraCharSurrogateLevel[m_oraCharSurrogateLevel[m_oraCharLevel1[num5] + num6] + num7] == '\uffff')
					{
						m_oraCharSurrogateLevel[m_oraCharSurrogateLevel[m_oraCharLevel1[num5] + num6] + num7] = c;
						c = (char)(c + 256);
					}
					if (m_oraCharLevel2[m_oraCharSurrogateLevel[m_oraCharSurrogateLevel[m_oraCharLevel1[num5] + num6] + num7] + num8] == '\uffff')
					{
						m_oraCharLevel2[m_oraCharSurrogateLevel[m_oraCharSurrogateLevel[m_oraCharLevel1[num5] + num6] + num7] + num8] = (char)((uint)array[1] & 0xFFFFu);
					}
				}
				else
				{
					if (m_oraCharLevel1[num7] == '\uffff')
					{
						m_oraCharLevel1[num7] = c;
						c = (char)(c + 256);
					}
					if (m_oraCharLevel2[m_oraCharLevel1[num7] + num8] == '\uffff')
					{
						m_oraCharLevel2[m_oraCharLevel1[num7] + num8] = (char)((uint)array[1] & 0xFFFFu);
					}
				}
			}
			if (extraUnicodeToOracleMapping != null)
			{
				num = extraUnicodeToOracleMapping.Length;
				for (int i = 0; i < num; i++)
				{
					int num2 = extraUnicodeToOracleMapping[i][0];
					if (num2 == m_ucsReplacement)
					{
						continue;
					}
					int num5 = (num2 >> 24) & 0xFF;
					int num6 = (num2 >> 16) & 0xFF;
					int num7 = (num2 >> 8) & 0xFF;
					int num8 = num2 & 0xFF;
					if (num5 >= 216 && num5 < 220)
					{
						if (m_oraCharLevel1[num5] == '\uffff')
						{
							m_oraCharLevel1[num5] = c2;
							c2 = (char)(c2 + 256);
						}
						if (m_oraCharSurrogateLevel[m_oraCharLevel1[num5] + num6] == '\uffff')
						{
							m_oraCharSurrogateLevel[m_oraCharLevel1[num5] + num6] = c2;
							c2 = (char)(c2 + 256);
						}
						if (m_oraCharSurrogateLevel[m_oraCharSurrogateLevel[m_oraCharLevel1[num5] + num6] + num7] == '\uffff')
						{
							m_oraCharSurrogateLevel[m_oraCharSurrogateLevel[m_oraCharLevel1[num5] + num6] + num7] = c;
							c = (char)(c + 256);
						}
						m_oraCharLevel2[m_oraCharSurrogateLevel[m_oraCharSurrogateLevel[m_oraCharLevel1[num5] + num6] + num7] + num8] = (char)((uint)extraUnicodeToOracleMapping[i][1] & 0xFFu);
					}
					else
					{
						if (m_oraCharLevel1[num7] == '\uffff')
						{
							m_oraCharLevel1[num7] = c;
							c = (char)(c + 256);
						}
						m_oraCharLevel2[m_oraCharLevel1[num7] + num8] = (char)((uint)extraUnicodeToOracleMapping[i][1] & 0xFFFFu);
					}
				}
			}
			if (m_oraCharSurrogateLevel == null)
			{
				noSurrogate = true;
			}
			else
			{
				noSurrogate = false;
			}
			strictASCII = true;
			for (int i = 0; i < 128; i++)
			{
				if (m_oraCharLevel2[i] != i)
				{
					strictASCII = false;
					break;
				}
			}
			for (int i = 0; i < 256; i++)
			{
				if (m_oraCharLevel1[i] == '\uffff')
				{
					m_oraCharLevel1[i] = (char)num4;
				}
			}
			m_oraCharLevel2Size = num4;
		}

		public override void ExtractCodepoints(IList<int[]> vtable)
		{
			int num = 255;
			for (int i = 0; i <= num; i++)
			{
				try
				{
					vtable.Add(new int[2]
					{
						i,
						ByteToChar((byte)i, useReplacement: true)
					});
				}
				catch
				{
				}
			}
		}

		public override void ExtractExtraMappings(IList<int[]> vtable)
		{
			if (extraUnicodeToOracleMapping != null)
			{
				for (int i = 0; i < extraUnicodeToOracleMapping.Length; i++)
				{
					vtable.Add(new int[2]
					{
						extraUnicodeToOracleMapping[i][0],
						extraUnicodeToOracleMapping[i][1]
					});
				}
			}
		}

		public override bool HasExtraMappings()
		{
			return extraUnicodeToOracleMapping != null;
		}

		public override char GetOraChar1ByteRep()
		{
			return (char)(m_oraCharReplacement & 0xFFu);
		}

		public override char GetOraChar2ByteRep()
		{
			return '\0';
		}

		public override int GetUCS2CharRep()
		{
			return m_ucsReplacement;
		}

		public override int ConvertBytesToChars(IList<ArraySegment<byte>> bytes, int offset, int count, char[] chars, int charOffset, ref int charCount, bool bUseReplacementChar)
		{
			int num = charOffset;
			int charCount2 = charCount;
			int num2 = 0;
			int num3 = 0;
			int idx = 0;
			int offSet = bytes[0].Offset;
			bool flag = false;
			if (offset > 0)
			{
				UTF16ConvUtility.GetSegementIndices(bytes, offset, ref idx, ref offSet);
			}
			for (int i = idx; i < bytes.Count; i++)
			{
				if (flag)
				{
					break;
				}
				if (charCount2 <= 0)
				{
					break;
				}
				int byteOffset = bytes[i].Offset;
				int num4 = bytes[i].Count;
				if (i == idx)
				{
					byteOffset = offSet;
					num4 = bytes[i].Count - (offSet - bytes[i].Offset);
				}
				if (count - num3 <= num4)
				{
					num4 = count - num3;
					flag = true;
				}
				num3 += ConvertBytesToChars(bytes[i].Array, byteOffset, num4, chars, num, ref charCount2, bUseReplacementChar);
				num += charCount2;
				num2 += charCount2;
				charCount2 = charCount - num2;
			}
			charCount = num2;
			return num3;
		}

		public override int GetCharsLength(byte[] bytes, int byteOffset, int byteCount)
		{
			if (byteOffset + byteCount > bytes.Length)
			{
				return bytes.Length - byteOffset;
			}
			return byteCount;
		}

		public override int GetCharsLength(ArraySegment<byte> bytes, int bytesOffset, int bytesCount)
		{
			if (bytesCount > bytes.Count)
			{
				return bytes.Count - bytesOffset;
			}
			return bytesCount;
		}

		public override int GetCharsLength(IList<ArraySegment<byte>> bytes, int bytesOffset, int bytesCount)
		{
			return bytesCount;
		}

		public override int GetBytesLength(char[] chars, int charOffset, int charCount)
		{
			if (charOffset + charCount > chars.Length)
			{
				return chars.Length - charOffset;
			}
			return charCount;
		}

		public override int GetBytesLength(string str, int strOffset, int strCount)
		{
			if (strOffset + strCount > str.Length)
			{
				return str.Length - strOffset;
			}
			return strCount;
		}

		public override int GetBytesLength(byte[] utf16Bytes, int utf16BytesOffset, int utf16BytesCount)
		{
			if (utf16BytesOffset + utf16BytesCount > utf16Bytes.Length)
			{
				return (utf16Bytes.Length - utf16BytesOffset) / 2;
			}
			return utf16BytesCount / 2;
		}

		public override int GetBytesOffset(byte[] bytes, int byteOffset, int byteCount, int charCount)
		{
			return charCount;
		}

		public override int GetBytesOffset(IList<ArraySegment<byte>> bytes, int charCount)
		{
			return charCount;
		}
	}
}
